home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
assemblr
/
library
/
sampler0
/
wt.asm
< prev
next >
Wrap
Assembly Source File
|
1987-03-12
|
23KB
|
471 lines
TITLE WalkTree - Execute Program at Every Level of Tree
; Copyright Notice:
;
; The program WalkTree, both in binary executable and source forms, is
; in the public domain. No warranty is given or implied, and no
; liability will be assumed by the author.
;
; Everyone on earth is hereby given permission to use, copy, distribute,
; change, mangle, destroy or otherwise employ these programs, in whole
; or in part, in any fashion they so desire, provided they hurt no one
; but themselves in the process.
;
; If anyone has any questions about this or any other program that I
; have authored, I can be reached by messages on any of the following
; systems:
;
; Bob's Answering Machine (602) 242-3158 300/1200 bps
; FIDO 114/1 Phoenix Node (602) 242-5230 300/1200/2400 bps
; FIDO 114/446 XTRA #1 (602) 979-6352 300/1200/2400 bps
; Technoids Anonymous (602) 899-4876 300/1200/2400 bps
;
; All excellent 24 hour systems.
;
; Don A. Williams
; 3913 W. Solano Dr. N.
; Phoenix, AZ 85019
; This version of the source for WalkTree has been set up for assembly by
; SpeedWare's very good TurboEditAsm. To convert it for assembly by
; Microsoft's MASM will require the addition of Segment and Assume
; statements, at least.
;
;
; version history
; modified by John Covici
; 3 Wirt Street NW
; Leesburg, VA 22075
; March 12, 1987 fixed the following bugs:
; (1) append cr to generated command line (if not dos goes out to lunch)
; (2) now assembles with masm
; (3) to get environment segment had to say [ds:2ch] instead of [2ch]
; otherwise assembler ignored brackets without error
LF EQU 0AH ; ASCII Line Feed
CR EQU 0DH ; ASCII Carriage Return
cseg segment para public 'code'
ORG 0100H
assume cs:cseg,ds:cseg,ss:cseg
Start: jmp Begin ; Jump over data area
;------ Messages
LogOn db 'WalkTree: Version 1.01 - March 12, 1987',CR,LF,LF,'$'
BadVer db 'WalkTree requires Dos 2.0 or greater',CR,LF,'$'
UseMsg db 'USAGE: WalkTree <any dos command>',CR,LF,'$'
EndMs1 db CR,LF,'Number of directories= $'
EndMs2 db ': Maximum depth= $'
EndMsg db '$'
AbtMsg db 'Program terminated by operator.',CR,LF,'$'
;------ Constants and Other Data Storage
Path db 0,':\',65 DUP(0)
PatMsg db CR,LF,LF,'---'
CurPat db 0,':\',65 DUP(0)
PatTer db '---',CR,LF,0
MatAll db '*.*',0
Parent db '..',0
CmdTail db 0,'/c '
CmdLin db 128 DUP(0)
ComSpc db 'COMSPEC',0
ComCom db '\COMMAND.COM',0
DTAOfs dw 0 ; Save space for DTA: Offset and
DTASeg dw 0 ; ... Segment
SaveSS dw 0 ; Save space for Stack; Segment and
SaveSP dw 0 ; ... Pointer
Level dw 0 ; Current depth in hierarchy
MaxLev dw 0 ; Maximum depth in hierarchy
DirCnt dw 0 ; Count of directories processed
comand db 65 dup(0) ;space for command.com from env or default
;------ Parameter Block for DOS function 4B, Exec
ParBlk dw 0 ; Seg of environment string
dw 0 ; Ofs of Command Tail string
dw 0 ; Seg " " " "
dw 0 ; Ofs of Default FCB 1
dw 0 ; Seg " " " "
dw 0 ; Ofs of Default FCB 2
dw 0 ; Seg " " " "
;=========================================================================
; Beginning of Program Code
Begin: mov SP,offset STACK ; Set local stack
cld ; Clear Direction Flag [forward]
mov DX,offset LogOn ; Dsiplay logon message
mov AH,9 ; ... MS-DOS 'Print String'
int 21H ; ... DOS Entry Interrupt
mov AH,30H ; MS-DOS 'Get Version'
int 21H ; ... DOS Entry Interrupt
cmp AL,2 ; Check for 2.x or greater
jnb VerOk ; ... Xfr- 2.x or greater
mov DX,offset BadVer ; Get ptr to 'bad version' msg
ErrorExit:
mov AH,9 ; MS-DOS 'Print String'
int 21H ; ... DOS Entry Interrupt
int 20H ; DOS Terminate Program Interrupt
VerOk: mov AH,19H ; MS-DOS 'Get Current Disk'
int 21H ; ... DOS Entry Interrupt
add AL,'A' ; Convert disk code to alpha disk
mov Path,AL ; ... and save in Path
mov CurPat,AL ; ... and in Current Path
mov SI,offset Path+3 ; Get Current Dir as starting path
mov DL,0 ; ... current disk
mov AH,47H ; ... MS-DOS 'Get Current Directory'
int 21H ; ... DOS Entry Interrupt
mov SI,80H ; Get ptr to Command Line buffer
lodsb ; ... and get length
or AL,AL ; Check for length zero - no tail
jnz HaveTail ; ... Xfr - length not zero
Usage:
mov DX,offset UseMsg ; Display 'Usage' message and
jmp short ErrorExit ; ... terminate
HaveTail:
cbw ; Make length 16 bits
mov CX,AX ; ... and move to CX for move
add AL,3 ; Adjust length for '/c '
mov CmdTail,AL ; ... and store for DOS 4BH
mov DI,offset CmdLin ; Get ptr to internal Cmnd Line
repz movsb ; Move command line to internal store
mov byte ptr[di],0dh ;append carriage return
mov BX,1000H ; Release all but 1000H paragraphs
mov AH,4AH ; ... MS-DOS 'Modify Allocated Memory'
int 21H ; ... DOS Entry Interrupt
call WalkTree ; Walk the tree recursively
mov DX,offset EndMs1 ; Print out run statistics
mov AH,9 ; ... MS-DOS 'Print String'
int 21H ; ... DOS Entry Interrupt
mov BX,DirCnt ; Display directory count in
call PrintDecimal ; ... decimal
mov DX,offset EndMs2 ; Display 2nd part of message
mov AH,9 ; ... MS-DOS 'Print String'
int 21H ; ... DOS Entry Interrupt
mov BX,MaxLev ; Display maximum level in
call PrintDecimal ; ... decimal
mov DX,offset EndMsg ; Get ptr final part of message
Terminate:
mov AH,9 ; MS-DOS 'Print String'
int 21H ; ... DOS Entry Interrupt
mov DX,offset Path ; Restore directory to starting
mov AH,3BH ; ... MS-DOS 'Change Subdirectory'
int 21H ; ... DOS Entry Interrupt
int 20H ; DOS Terminate Program
;=========================================================================
; WalkTree is a recursive subroutine that processes each level of the
; directory hierarchy. Each invocation of Walktree creates and uses a
; 50 byte stack frame containing the Segment and Offset of the prior
; level's DTA, the name of the current subdirectory, and a pointer to its
; own stack frame.
WalkTree:
mov SI,offset CurPat+3 ; Get current directory name
mov DL,0 ; ... current disk
mov AH,47H ; ... MS-DOS 'Get Current Directory'
int 21H ; ... DOS Entry Interrupt
mov SI,offset PatMsg ; Display Current directory
call PrintString ; ...
mov SI,offset PatTer ; Terminate Current directory
call PrintString ; ...
inc DirCnt ; Incr count of directories
mov AX,Level ; Incr level
inc AX ; ...
mov Level,AX ; ... and store updated value
cmp AX,MaxLev ; Update Maximum level, if necessary
jbe WT1 ; ... Xfr - not necessary
mov MaxLev,AX ; ...
WT1: push BP ; Save old stack frame ptr
sub SP,49 ; ... and get new stack frame
mov BP,SP ; ...
add BP,4 ; ... leave room for DTA adr
push ES ; Save ES over DOS call
mov AH,2FH ; MS-DOS 'Get DTA'
int 21H ; DOS Entry Interrupt
mov [BP-4],BX ; Save DTA offset and DTA segment
mov [BP-2],ES ; ... in stack frame
pop ES ; Restore saved ES
mov DX,BP ; Set DTA to Stack frame
mov AH,1AH ; ... MS-DOS 'Set DTA'
int 21H ; ... DOS Entry Interrupt
call CheckAbort ; Check for operator abort
call Execute
mov DX,offset MatAll ; Get ptr to ALL match string
mov CX,10H ; ... set attribute for Subdirectory
mov AH,4EH ; ... MS-DOS 'Find 1st Match'
int 21H ; ... DOS Entry Interrupt
jb PopLevel ; ... Xfr - Had error
ProcessSub:
test byte ptr [BP+21],10H ; Check for Subdirectory
jz GetNextSub ; ... Xfr - not Subdirectory
cmp byte ptr [BP+30],'.' ; Check for 'parent' or 'self' entries
jz GetNextSub ; ... Xfr - 'parent' or 'self'
mov DX,BP ; Get ptr to DTA
add DX,30 ; ... and compute name ptr
mov AH,3BH ; MS-DOS 'Change SubDirectory'
int 21H ; ... DOS Entry Interrupt
call CheckAbort ; Check for operator abort
call WalkTree ; Walk the tree of new directory
GetNextSub:
mov AH,4FH ; MS-DOS 'Find Next Match'
mov CX,10H ; ... set attribute for directory
int 21H ; ... DOS Entry Interrupt
jb PopLevel ; ... Xfr - error - no more matches
jmp short ProcessSub ; Loop through directory
PopLevel:
mov DX,offset Parent ; Get ptr to 'Parent' string
mov AH,3BH ; ... MS-DOS 'Change SubDirectory'
int 21H ; ... DOS Entry Interrupt
push DS ; Save DS
mov DS,[BP-2] ; Restore prior DTA from stack
mov DX,[BP-4] ; ... frame
mov AH,1AH ; MS-DOS 'Set DTA'
int 21H ; ... DOS Entry Interrupt
pop DS ; Restore saved DS
dec Level ; Decr directory level count
add SP,49 ; Delete stack frame
pop BP ; Restore stack frame ptr
ret
; End of WalkTree
;-------------------------------------------------------------------------
;=========================================================================
; CheckAbort is used to check for an Operator Abort [any key pressed
; during execution.
CheckAbort:
mov AH,0BH ; MS-DOS 'Check StdIn Status'
int 21H ; ... DOS Entry Interrupt
or AL,AL ; Check for Char ready
jz CAExit ; ... Xfr - no char ready
mov AH,08H ; MS-DOS 'Console In, No Echo'
int 21H ; ... DOS Entry Interrupt
mov DX,offset AbtMsg ; Get ptr to 'abort' message
jmp Terminate ; ... and terminate program
CAExit: ret
; End of CheckAbort
;-------------------------------------------------------------------------
;=========================================================================
; Execute is used to execute the program specified on WalkTree's Command
; line. It uses MS-DOS Function 21H, SubFunction 4BH [Exec] to execute
; COMMAND.COM as a child. It searches the Environment to find COMSPEC
; in order to call COMMAND.COM
Execute:
push BP ; Save caller's registers
push DS ; ...
push ES ; ...
push ES ; Save ES over CALL
mov AH,2FH ; MS-DOS 'Get DTA'
int 21H ; ... DOS Entry Interrupt
mov DTASeg,ES ; Save DTA segment
mov DTAOfs,BX ; ... and Offset
pop ES ; Restore saved ES
mov AX,CS ; Get segment for DOS 4B
mov ParBlk+4,AX ; ... and store as Command Tail Seg
mov ParBlk+8,AX ; ... and as FCB 1 Seg
mov ParBlk+12,AX ; ... and as FCB 2 Seg
mov ParBlk+2,offset CmdTail ; Store offset of Cmnd Tail
mov ParBlk+6,5CH ; ... and offset of FCB 1
mov ParBlk+10,6CH ; ... and offset of FCB 2
mov DI,offset ComSpc
mov bx,[ds:2ch] ;get environment string segment
mov ParBlk,BX ; ... to Parameter Blk for DOS 4BH
call FindComSpec ; Search environment for COMSPEC
jnc GotComSpec ; ... Xfr - found COMSPEC
mov AX,CS ; Set DS to local data space
mov DS,AX ; ...
mov dx, offset ComCom ;get ptr to 'command.com'
jmp short goexec
GotComSpec:
mov di,offset comand ; dest offset of comand in di
mov cl,65;large enough number
smov1:
lodsb ;load byte in al
stosb ;store byte in comand
or al,al
loopnz smov1
mov AX,CS ; Set DS to local data space
mov DS,AX ; ...
mov dx,offset comand;file name to execute
goexec:
mov BX,offset ParBlk ; Get ptr to Parameter Block for DOS 4BH
mov CS:SaveSS,SS ; Save Stack Segment & offset over
mov CS:SaveSP,SP ; ... Exec call
mov AX,4B00H ; MS-DOS 'Load & Execute Program'
int 21H ; ... DOS Entry Interrupt
cli ; Inhibit interrupts
mov SS,CS:SaveSS ; Restore Stack Segment &
mov SP,CS:SaveSP ; ... Offset
sti ; Enable interrupts
mov DS,CS:DTASeg ; Restore local data space
mov DX,CS:DTAOfs
mov AH,1AH ; MS-DOS 'Set DTA'
int 21H ; ... DOS Entry Interrupt
pop ES
pop DS
pop BP
ret
; End of Execute
;-------------------------------------------------------------------------
;=========================================================================
; FindComSpec is used by Execute to locate COMSPEC in the Environment and
; the name of COMMAND.COM to pass to MS-DOS 21H, SubFunction 4B [Exec].
FindComSpec:
mov DS,BX ; Set data space to Environment
mov DI,offset ComSpc ; Get ptr to 'COMSPEC' for search
sub SI,SI ; Start at relative 0 in Environment
mov CX,7 ; Get length of 'COMSPEC'
XFCS3: lodsb ; Get byte from Environment
or AL,AL ; Check for end of entry
jnz XFCS4 ; ... Xfr - not end of entry
cmp byte ptr [SI+1],0 ; Check for end of Environment
jz XFCS5 ; ... Xfr - end of Environment
XFCS4: call UpCase ; Convert to upper case and
mov [SI-1],AL ; ... store back in Environment
cmp AL,'=' ; Check for '=' as in 'COMSPEC='
jnz XFCS3 ; ... Xfr - not '='
push SI ; Save both ptrs and length
push DI ; ...
push CX ; ...
sub SI,2 ; Back up SI to end of string
std ; Set Direction Flag [reverse]
repnz cmpsb ; Compare Envirn string to 'COMSPEC'
cld ; Clear Direction Flag [forward]
pop CX ; Restore length and both ptrs
pop DI ; ...
pop SI ; ...
jnz XFCS3 ; Xfr - did not match 'COMSPEC'
clc ; Clear CARRY for good return
ret
XFCS5: stc ; Set CARRY for error return
ret
; End of FindComSpec
;-------------------------------------------------------------------------
;=========================================================================
; UpCase is a utility subroutine to convert the lower case alpha char in
; AL to upper case. Only lower case alphas are affected, any other char
; in AL is returned unmodified.
UpCase: cmp AL,'a' ; Check upper bound of lower case
jb UCExit ; ... Xfr - not lower case - too low
cmp AL,'z' ; Check upper bound of lower case
ja UCExit ; ... Xfr - not lower case - too high
and AL,0DFH ; Convert char to upper case
UCExit: ret
;End of UpCase
;-------------------------------------------------------------------------
;=========================================================================
; PrintDecimal is a utility subroutine used to convert the 16-bit integer
; in BX to decimal and display it on StdOut as a 5-digit figure with
; blank suppression of leading zeros. It is overkill for the current
; version of WalkTree.
PrintDecimal:
mov CL,0
mov DX,10000 ; Get 10,000s digit and display
call PrintDigit ; ... it
mov DX,1000 ; Get 1,000s digit and display
call PrintDigit ; ... it
mov DX,100 ; Get 100s digit and display
call PrintDigit ; ... it
mov DX,10 ; Get 10s digit and display
call PrintDigit ; ... it
mov CH,BL ; Display units digit [no zero
jmp short XPD2 ; ... suppression]
PrintDigit:
mov CH,0FFH ; Initialize result
XPD1: inc CH ; Incr result
sub BX,DX ; Divide by repetitive subtraction
jnb XPD1 ; ... Xfr - not there yet
add BX,DX ; Correct for overshoot
cmp CH,0 ; Check result for zero
jnz XPD2 ; ... Xfr - not zero result
test CL,1 ; Test for leading zero
jnz XPD2 ; ... Xfr - not leading zero
ret
XPD2: push DX ; Save divisor
mov DL,CH ; Move digit to DL for DOS
add DL,'0' ; Convert digit to ASCII
mov AH,2 ; MS-DOS 'Console Output
int 21H ; ... DOS ENtry Interrupt
pop DX ; Restore divisor
mov CL,1 ; Turn OFF zero suppression
ret
; End of PrintDecimal
;-------------------------------------------------------------------------
;=========================================================================
; PrintString is a utility subroutine to display a NULL-terminated ASCII
; string on StdOut. On input, SI contains the address of the string to
; be displayed. All other registers are preserved.
PrintString:
push AX
push DX
PS1: lodsb
or AL,AL
jz PSExit
mov DL,AL
mov AH,02H
int 21H
jmp short PS1
PSExit: pop DX
pop AX
ret
;End of PrintString
;-------------------------------------------------------------------------
;=========================================================================
; Stack space. Since each invocation of the WalkTree subroutine creates a
; 50 byte stack frame on this stack, 3000 bytes of stack would allow for
; approximately 60 levels in the directory hierarchy, probably extreme
; overkill.
STACK EQU $+3000
cseg ends
end Start